"""
Contains classes used for describing movements. Simple movements
can use just move, but movements involving multiple segments should
use a plot, assuming they need validation.
"""

import directions
import logging


class Plot:
	"""
	Represents a plot. Treat as a list. Handles movement validation whenever a
	plot item is added. Not designed for general use.
	"""
	owner = None
	data = None
	_points = None
	
	def __init__(self, boat, data=None, **kwargs):
		super(Plot, self).__init__(**kwargs)
		self.log = logging.getLogger('engine.plot')
		self.log.debug( "Plot Init: #%X %s#%X" %
							(id(self), boat, id(boat)) )
		self.owner = boat
		if data is not None:
			self.data = data
			self._validate([])
		else:
			self.data = []
			
	def __del__(self):
		self.log.debug( "Plot Del : #%X %s#%X" %
						(id(self), self.owner, id(self.owner)) )
		
	def __str__(self):
		return str(self.data)
	
	def __repr__(self):
		return 'plot(%r, %r)' % (self.owner, self.data)
	
	def __setitem__(self, item, value):
		old = self.data[:]
		self.data[item] = value
		self._validate(old)
		
	def __getitem__(self, item):
		return self.data[item]
	
	def __delitem__(self, item):
		old = self.data[:]
		self.data.__delitem__(item)
		self._validate(old)
		
	def __len__(self):
		return len(self.data)
	
	def __iter__(self):
		for i in self.data:
			yield i
			
	def append(self, item):
		old = self.data[:]
		self.data += [item]
		self._validate(old)
		
	def __iadd__(self, item):
		old = self.data[:]
		self.data += item
		self._validate(old)
		return self
	
	def _validate(self, backup):
		try:
			self.owner.validatePlot()
			self._points = []
		except:
			self.data = backup
			raise
	
	def points(self):
		if len(self._points) != len(self.data) + 1:
			rv = [self.owner.location]
			for v in self.data:
				angle = v.dir.angle.radians().value
				p = Point.fromVector(angle, v.dist)
				t = rv[-1] + p
				rv.append(t)
			self._points = rv
			return rv
		else:
			return self._points

class Move(object):
	"""
	Represents a segment of a plotted move.
	"""
	direction = directions.North
	distance = 0
	
	def __init__(self, odir=directions.North, dist=0, **kwargs):
		super(Move, self).__init__(**kwargs)
		self.direction = odir
		self.distance = dist
	
	def __str__(self):
		return '%0.1f" %s' % (self.distance, self.direction)
	
	def __repr__(self):
		return 'move(%r, %0.1f)' % (self.direction, self.distance)
	
	def _getdir(self):
		return self.direction
	
	def _setdir(self, value):
		self.direction = value
	dir = property(_getdir, _setdir)
	
	def _getdist(self):
		return self.distance
	
	def _setdist(self, value):
		self.distance = value
	dist = property(_getdist, _setdist)


